package fhq.hcmute.edu.vn.activities;

import java.io.IOException;

import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnKeyListener;
import android.view.View.OnTouchListener;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import fhq.hcmute.edu.vn.gestures.MyGestures;
import fhq.hcmute.edu.vn.gestures.TouchManager;
import fhq.hcmute.edu.vn.gestures.TouchPoint;
import fhq.hcmute.edu.vn.keyboard.KeyCode;
import fhq.hcmute.edu.vn.languages.Language;
import fhq.hcmute.edu.vn.message.MessageFactory;
import fhq.hcmute.edu.vn.message.MyMessage;
import fhq.hcmute.edu.vn.network.Network;
import fhq.hcmute.edu.vn.util.SharePreferencesUtil.TouchPadSetting;

/**
 * @author Hien Nguyen Sep 24, 2012
 */
public class TouchPadActivity extends Activity implements OnTouchListener {

	private static final float DEFAULT_MOUSE_MOVE_SENSITIVE = 1.0F;
	private Button btnMouseLeft;
	private Button btnMouseRight;
	private EditText edtKeyboadInput;
	private LinearLayout touchPad;
	private Network network;
	private int currentDash = 0;
	private int from;
	private float mouseMoveSensitive = DEFAULT_MOUSE_MOVE_SENSITIVE;
	private int mouseScrollSensitive = 1;
	private TouchManager touchManager;
	private MyGestures gestures;
	private boolean isTapToClick = false;
	private boolean isLeftHandMode = false;
	private boolean isKeepScreenOn = false;

	@Override
	protected final void onCreate(final Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		Language.updateLanguageSystem(getBaseContext());
		setContentView(R.layout.activity_touchpad);
		init();
		updateTouchPadSetting();
	}

	private void updateTouchPadSetting() {
		SharedPreferences preferences = getSharedPreferences(
				TouchPadSetting.TOUCHPAD_SETTING, 0);
		mouseMoveSensitive = preferences.getFloat(
				TouchPadSetting.TOUCHPAD_SENSITIVITY,
				DEFAULT_MOUSE_MOVE_SENSITIVE);
		mouseScrollSensitive = preferences
				.getInt(TouchPadSetting.MOUSE_SCROLL_SENSITIVITY, 1);
		isKeepScreenOn =
				preferences.getBoolean(TouchPadSetting.KEEP_SCREEN_ON, false);

		// prevent screen dim off
		if (isKeepScreenOn) {
			getWindow().addFlags(
					WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
		} else {
			getWindow().clearFlags(
					WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
		}
		isLeftHandMode =
				preferences.getBoolean(TouchPadSetting.LEFT_HAND_MODE, false);
		isTapToClick =
				preferences.getBoolean(TouchPadSetting.TAP_TO_CLICK, false);
	}

	private void init() {
		touchPad = (LinearLayout) findViewById(R.id.touchpad);
		touchPad.setOnTouchListener(this);
		network = Network.getInstance();
		btnMouseLeft = (Button) findViewById(R.id.btnMouseLeft);
		btnMouseLeft.setOnClickListener(onClickLeftButton);
		btnMouseRight = (Button) findViewById(R.id.btnMouseRight);
		btnMouseRight.setOnClickListener(onClickRightButton);
		edtKeyboadInput = (EditText) findViewById(R.id.edtKeyboard);
		edtKeyboadInput.setOnClickListener(onKeyboadInputClickListener);
		edtKeyboadInput.addTextChangedListener(onKeyboadInputTextChange);
		edtKeyboadInput.setOnKeyListener(onKeyboadInputKeyListener);
		touchManager = new TouchManager();
		gestures = new MyGestures(touchManager);
	}

	private TextWatcher onKeyboadInputTextChange = new TextWatcher() {

		@Override
		public void onTextChanged(CharSequence s, int start, int before,
				int count) {
			if (before == 0 && count == 1) {
				int end = s.length() - 1;
				if (end >= 0) {
					char c = s.charAt(start);
					KeyCode code = KeyCode.fromString(c, KeyCode.TELEX);
					if (!code.equals(KeyCode.UNDEFINED)) {
						from = start + 1;
						currentDash = end - start;
						MyMessage message = MessageFactory
								.createKeyboardPressMessage(
										currentDash, code);
						try {
							network.sendToServer(message);
						} catch (IOException e) {
							e.printStackTrace();
						}
					} else {
						String k = edtKeyboadInput.getText().toString();
						String newData =
								k.replaceAll(Character.toString(c), "");
						edtKeyboadInput.setText(newData);
						edtKeyboadInput.setSelection(newData.length());
					}
				}
			}
		}

		@Override
		public void beforeTextChanged(CharSequence s, int start, int count,
				int after) {

		}

		@Override
		public void afterTextChanged(Editable s) {
		}
	};

	private OnClickListener onKeyboadInputClickListener =
			new OnClickListener() {
				private int to;

				@Override
				public void onClick(View v) {
					to = edtKeyboadInput.getSelectionStart();
					MyMessage message;
					if (from > to) {
						message =
								MessageFactory.createKeyboardPressLeft(from
										- to);
					} else {
						message =
								MessageFactory.createKeyboardPressRight(to
										- from);
					}
					try {
						network.sendToServer(message);
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					from = to;
				}
			};

	private OnKeyListener onKeyboadInputKeyListener = new OnKeyListener() {

		@Override
		public boolean onKey(View v, int keyCode, KeyEvent event) {
			MyMessage message = null;
			if (event.getAction() == KeyEvent.ACTION_DOWN) {
				if (keyCode == KeyEvent.KEYCODE_DEL) {
					message = MessageFactory.createKeyboardPressMessage(
							currentDash, KeyCode.BACK_SPACE);
				} else if (keyCode == KeyEvent.KEYCODE_ENTER) {
					message = MessageFactory.createKeyboardPressMessage(
							currentDash, KeyCode.ENTER);
				}
				try {
					network.sendToServer(message);
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			return false;
		}
	};

	@Override
	public final void onBackPressed() {
		if (edtKeyboadInput.getVisibility() == View.GONE) {
			super.onBackPressed();
		}
		if (edtKeyboadInput.getVisibility() == View.VISIBLE) {
			edtKeyboadInput.setVisibility(View.GONE);
		}

	}

	private OnClickListener onClickLeftButton = new OnClickListener() {

		@Override
		public void onClick(final View v) {
			if (isLeftHandMode) {
				rightClick();
			} else {
				leftClick();
			}
		}
	};
	private OnClickListener onClickRightButton = new OnClickListener() {

		@Override
		public void onClick(final View v) {
			if (isLeftHandMode) {
				leftClick();
			} else {
				rightClick();
			}

		}
	};

	private void leftClick() {
		MyMessage myMessage = MessageFactory.createMouseLeftClickMessage();
		try {
			network.sendToServer(myMessage);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private void rightClick() {
		MyMessage myMessage = MessageFactory.createMouseRightClickMessage();
		try {
			network.sendToServer(myMessage);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public final boolean onTouch(final View v, final MotionEvent event) {
		touchManager.updateTouchPoints(event);
		MyMessage message = null;
		TouchPoint current = null;
		TouchPoint previous = null;
		float xMove = 0.0F;
		float yMove = 0.0F;
		switch (gestures.getGestures()) {
		case MyGestures.TAP:
			if (isTapToClick) {
				message = MessageFactory.createMouseLeftClickMessage();
			}
			break;
		case MyGestures.DROP:
			message = MessageFactory.createDropMessage();
			break;
		case MyGestures.DRAP:
			message = MessageFactory.createDrapMessage();
			break;
		case MyGestures.SCROLL_UP:
			message = MessageFactory
					.createScrollUpMessage(mouseScrollSensitive);
			break;
		case MyGestures.SCROLL_DOWN:
			message = MessageFactory
					.createScrollDownMessage(mouseScrollSensitive);
			break;
		case MyGestures.ZOOM_IN:
			message = MessageFactory.createZoomInMessage();
			break;
		case MyGestures.ZOOM_OUT:
			message = MessageFactory.createZoomOutMessage();
			break;
		case MyGestures.MOVE:
			current = touchManager.getCurrentTouchPointAt(0);
			previous = touchManager.getPreviousTouchPointAt(0);
			xMove = current.getX() - previous.getX();
			yMove = current.getY() - previous.getY();
			if (!previous.isZero()) {
				message = MessageFactory.createMovementMessage(
						xMove * mouseMoveSensitive,
						yMove * mouseMoveSensitive);
			}
			break;
		default:
			break;
		}
		if (message != null) {
			sendMessageToServer(message);
			message = null;
		}
		return true;
	}

	private boolean sendMessageToServer(MyMessage message) {
		try {
			network.sendToServer(message);
			return true;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return false;
	}

	@Override
	public final boolean onMenuItemSelected(int featureId, MenuItem item) {
		switch (item.getItemId()) {
		case R.id.menuItemKeyboard:
			edtKeyboadInput.setVisibility(View.VISIBLE);
			break;
		case R.id.menuItemSetting:
			Intent intent =
					new Intent(getApplicationContext(),
							TouchPadSettingActivity.class);
			startActivity(intent);
			break;
		case R.id.menuItemExit:
			finish();
			break;
		default:
			break;
		}
		return super.onMenuItemSelected(featureId, item);
	}

	@Override
	public final boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.option_menu_touchpad_activity, menu);
		return super.onCreateOptionsMenu(menu);
	}

	@Override
	protected final void onResume() {
		updateTouchPadSetting();
		super.onResume();
	}

	@Override
	protected void onPause() {
		getWindow().clearFlags(
				WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
		super.onPause();
	}
}
